package com.gc.web.controller.api;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gc.business.domain.CompanyManage;
import com.gc.business.domain.RegisterAgreement;
import com.gc.business.domain.VerificationCode;
import com.gc.business.service.ICompanyManageService;
import com.gc.business.service.IRegisterAgreementService;
import com.gc.business.service.IVerificationCodeService;
import com.gc.common.annotation.Log;
import com.gc.common.base.AjaxResult;
import com.gc.common.config.Global;
import com.gc.common.constant.BusinessConstants;
import com.gc.common.constant.Constants;
import com.gc.common.constant.UserConstants;
import com.gc.common.enums.BusinessType;
import com.gc.common.utils.IdUtils;
import com.gc.common.utils.JwtUtil;
import com.gc.common.utils.RegexUtils;
import com.gc.common.utils.StringUtils;
import com.gc.framework.shiro.service.SysPasswordService;
import com.gc.framework.util.FileUploadUtils;
import com.gc.framework.util.ShiroUtils;
import com.gc.framework.web.base.ApiBaseController;
import com.gc.system.domain.SysRole;
import com.gc.system.domain.SysUser;
import com.gc.system.service.ISysUserService;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

/**
 * @author liujimteng
 * @title 登陆相关 用户信息 接口层
 * @date 2020-11-17
 */
@CrossOrigin
@Controller
@RequestMapping("/api/sysUser")
public class ApiSysUserController extends ApiBaseController {

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private SysPasswordService passwordService;

    @Autowired
    private ICompanyManageService companyManageService;

    @Autowired
    private IVerificationCodeService verificationCodeService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private IRegisterAgreementService registerAgreementService;

    /**
     * 获取验证码
     *
     * @param phoneNumber 手机号码
     * @return 返回参数
     */
    @PostMapping("/sendPhoneCode")
    @ResponseBody
    public Map<String, Object> sendPhoneCode(String phoneNumber) {
        if (StringUtils.isEmpty(phoneNumber)) {
            return error(Constants.UNVERIFY, "请输入手机号");
        }
        //判断手机号
        if (!RegexUtils.isMobile(phoneNumber)) {
            return error(Constants.UNVERIFY, "手机号格式不正确");
        }
        //校验发送验证码频繁性
        if (!checkLastCode(phoneNumber)) {
            return error("-2", "发送过于频繁，请稍后再试");
        }
        //生成六位数验证
        String verificationCode = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        //删除之前生成的验证码
        LambdaQueryWrapper<VerificationCode> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VerificationCode::getPhoneNum, phoneNumber);
        verificationCodeService.remove(wrapper);
        //最新验证码存入数据库中
        VerificationCode verificationCodeDataBase = new VerificationCode();
        verificationCodeDataBase.setPhoneNum(phoneNumber);
        verificationCodeDataBase.setPhoneCode(verificationCode);
        verificationCodeDataBase.setCreateTime(DateUtil.date());
        verificationCodeDataBase.setDeadTime(new Date(DateUtil.date().getTime() + 180000));//3min
        verificationCodeService.save(verificationCodeDataBase);
        String phoneCode = verificationCodeDataBase.getPhoneCode();
        if (StringUtils.isEmpty(phoneCode)) {
            return error(Constants.UNVERIFY, "验证码发送失败");
        }


        //接口发送验证码
        String messageApiUrl = "http://smssh1.253.com/msg/send/json";

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("account", "N134141_N4253376");
        jsonObject.put("password", "HjoCZmgle46a7d");
        jsonObject.put("msg", "【电梯安全公共服务平台】您的验证码是：" + verificationCode);
        jsonObject.put("phone", phoneNumber);

        String result = restTemplate.postForObject(messageApiUrl, jsonObject, String.class);

        Console.log("result:{}", result);

        Console.log("获取的验证码:" + phoneCode);
        return success(phoneCode);
    }

    /**
     * 检测请求频繁性
     *
     * @param phoneNum 手机号
     * @return
     */
    private boolean checkLastCode(String phoneNum) {
        VerificationCode lastCode = verificationCodeService.selectCodeByNew(phoneNum);
        if (lastCode != null) {
            Calendar c = Calendar.getInstance();
            c.add(Calendar.MINUTE, -1);
            //最后一次请求早于一分钟之前
            return lastCode.getCreateTime().before(c.getTime());
        }
        return true;
    }


    /**
     * 注册
     *
     * @param phoneNumber 手机号
     * @return 返回参数
     */
    @PostMapping("/register")
    @ResponseBody
    public Map<String, Object> register(String phoneNumber, String code,String password) {
        if (StringUtils.isEmpty(phoneNumber)) {
            return error(Constants.UNVERIFY, "请输入手机号");
        }
        if (StringUtils.isEmpty(code)) {
            return error(Constants.UNVERIFY, "请输入验证码");
        }
        if (StringUtils.isEmpty(password)) {
            return error(Constants.UNVERIFY, "请输入密码");
        }
        //判断手机号
        if (!RegexUtils.isMobile(phoneNumber)) {
            return error(Constants.UNVERIFY, "手机号格式不正确");
        }
        SysUser user = sysUserService.selectUserByPhoneNumber(phoneNumber);
        if (user != null) {
            return error(Constants.UNVERIFY, "手机号已注册");
        }
        //校验验证码
        VerificationCode verificationCode = verificationCodeService.selectCodeByNew(phoneNumber);
        if (verificationCode == null){
            return error(Constants.UNVERIFY, "验证码有误，请重新输入");
        }
        String phoneCode = verificationCode.getPhoneCode();
        Console.log("code:{};phoneCode:{}", code, phoneCode);
        if (DateUtil.date().getTime() >= verificationCode.getDeadTime().getTime()) {
            return error(Constants.UNVERIFY, "验证码已失效");
        }
        if (!code.equals(phoneCode)) {
            return error(Constants.UNVERIFY, "验证码错误");
        }
        //校验密码长度  都是5-20位
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            return error(Constants.UNVERIFY,"密码格式错误,请输入5到20个字符");
        }
        SysUser sysUser = new SysUser();
        sysUser.setLoginName(phoneNumber);
        sysUser.setSalt(ShiroUtils.randomSalt());
        sysUser.setPassword(passwordService.encryptPassword(sysUser.getLoginName(), password, sysUser.getSalt()));
        sysUser.setUserName("zhwb_" + IdUtils.getRandomNum());
        sysUser.setPhonenumber(phoneNumber);
        sysUser.setReviewStatus("0");
        sysUser.setAvatar(Global.getConfig("gc.default_avatar_url"));
        int row = sysUserService.insertUser(sysUser);
        if (row > 0) {
            return success("注册成功");
        } else {
            return error(Constants.UNVERIFY, "注册失败");
        }
    }

    /**
     * 账号密码登录
     *
     * @param loginName 登录用户名
     * @param password  密码
     * @param code      验证码
     * @param loginType 登录类型(0:手机号登录;1:账号密码登录)
     * @return
     */
    @PostMapping("/login")
    @ResponseBody
    public Map<String, Object> login(String loginName, String password, String code, Integer loginType, int rememberMe,String cid) {
        Map<String, Object> map = new HashMap<String, Object>();
        if (loginType == null) {
            return error(Constants.UNVERIFY, "参数错误:登录类型为空");
        }
        SysUser user = sysUserService.selectUserByLoginName(loginName);
        if (user == null) {
            return error("1005", "账号不存在");
        }
        if ("1".equals(user.getStatus())) {
            return error(Constants.UNVERIFY, "用户已被停用，请联系管理员");
        }
        //手机号登录
        if (loginType == 0) {
            //校验验证码
            VerificationCode verificationCode = verificationCodeService.selectCodeByNew(loginName);
            String phoneCode = verificationCode.getPhoneCode();
            if (DateUtil.date().getTime() >= verificationCode.getDeadTime().getTime()) {
                return error(Constants.UNVERIFY, "验证码已失效");
            }
            if (!code.equals(phoneCode)) {
                return error(Constants.UNVERIFY, "验证码错误");
            }

            //账号密码登录
        } else if (loginType == 1) {
            String salt = user.getSalt();
            String encryptPassword = passwordService.encryptPassword(loginName, password, salt);
            if (!user.getPassword().equals(encryptPassword)) {
                return error("1001", "密码错误");
            }
        }
        if(user.getAttrId() != null){
            //只有公司账户才能登录
            SysRole sysRole = sysUserService.checkUserRoleByAttrId(user.getAttrId());
            if (sysRole == null || StringUtils.isEmpty(sysRole.getRoleKey()) || !(sysRole.getRoleKey().equals(BusinessConstants.COMPANY))) {
                return error("1006", "该用户不是公司人员");
            }
        }
        //查看账号状态
        if (!user.getStatus().equals("0")) {
            return error("1002", "账号已被停用");
        }
        long ttlMillis = 0L;
        if (rememberMe > 0) {//记住我选项
            // 有效时间：一年
            ttlMillis = (24 * 60 * 60 * 1000) * 365;
        } else {
            // 有效时间：7天
            ttlMillis = (24 * 60 * 60 * 1000) * 7;
        }
        //生成token
        String token = JwtUtil.createJWT(String.valueOf(user.getUserId()), user.getLoginName(), ttlMillis);
        //最后登录时间
        user.setLoginDate(new Date());
        //生成token存储密码
        String loginToken = JwtUtil.createJWT(String.valueOf(user.getUserId()), password, ttlMillis);
        user.setLoginToken(loginToken);
        //保存CID
        user.setCid(cid);
        sysUserService.updateUserInfo(user);
        map.put("token", token);
        map.put("user", user);
        map.put("rememberMe", rememberMe);
        return AjaxResult.success(map);
    }

    /**
     * 查询用户信息
     *
     * @param token
     * @return
     */
    @ResponseBody
    @GetMapping("/selectSysUserById")
    public Map<String, Object> selectSysUserById(String token) {
        if (StringUtils.isNull(token)) {
            return AjaxResult.error("缺少必填参数：token");
        }
        Long userId = JwtUtil.getUserId(token);
        SysUser sysUser = sysUserService.selectUserById(userId);
        List<CompanyManage> companyList = new ArrayList<>();
        LambdaQueryWrapper<CompanyManage> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(sysUser.getAttrId())) {
            wrapper.eq(CompanyManage::getCompanyId, sysUser.getAttrId());
            companyList = companyManageService.list(wrapper);
            sysUser.setCompanyName(companyList.get(0).getCompanyName());
        }
        if (StringUtils.isNotNull(sysUser.getAvatar()) && !sysUser.getAvatar().contains("http")) {
            sysUser.setAvatar(Global.getConfig("gc.default_avatar_url"));
        }
        return success(sysUser);
    }


    /**
     * 上传用户头像，返回头像地址
     */
    @PostMapping("/uploadAvatar")
    @ResponseBody
    public Map<String, Object> updateAvatar(@RequestParam("avatarfile") MultipartFile file) {
        try {
            if (!file.isEmpty()) {
                String avatar = FileUploadUtils.upload(Global.getUploadPath(), file);
                return success(avatar);
            }
            return error(Constants.UNVERIFY, "服务错误，请稍后再试！");
        } catch (Exception e) {
            return error(Constants.UNVERIFY, e.getMessage());
        }
    }


    /**
     * 上传用户的电子签章图片
     *
     * @param file
     * @return
     */
    @PostMapping("/updateSignature")
    @ResponseBody
    public Map<String, Object> updateSignature(@RequestParam("file") MultipartFile file) {
        try {
            if (!file.isEmpty()) {
                String avatar = null;//FileUploadUtils.upload(Global.getSignaturePath(), file);
                return success(avatar);
            }
            return error(Constants.UNVERIFY, "服务错误，请稍后再试！");
        } catch (Exception e) {
            return error(Constants.UNVERIFY, e.getMessage());
        }
    }


    /**
     * 修改用户基本信息接口
     *
     * @param user
     * @return
     */
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @ResponseBody
    @PostMapping("/updateUserInfo")
    public Map<String, Object> updateUserInfo(String token, SysUser user) {

        Long userId = JwtUtil.getUserId(token);
        user.setUserId(userId);

        return success(sysUserService.updateUserInfo(user));
    }


    /**
     * 重置密码接口
     *
     * @param oldPassword
     * @param newPassword
     * @return
     */
    @Log(title = "重置密码", businessType = BusinessType.UPDATE)
    @PostMapping("/resetPwd")
    @ResponseBody
    public Map<String, Object> resetPwd(String token, String oldPassword, String newPassword) {
        SysUser user = sysUserService.selectUserById(getUserId(token));
        if (StringUtils.isEmpty(oldPassword)){
            return error(Constants.UNVERIFY, "参数错误，请输入原密码！");
        }
        if(StringUtils.isEmpty(newPassword)){
            return error(Constants.UNVERIFY, "参数错误，请输入新密码！");
        }
        //校验密码长度  都是5-20位
        if (newPassword.length() < UserConstants.PASSWORD_MIN_LENGTH || newPassword.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            return error(Constants.UNVERIFY,"密码格式错误,请输入5到20个字符");
        }
        if (StringUtils.isNull(user)) {
            return error(Constants.UNVERIFY, "用户信息已失效，请重新登录！");
        }
        if (!passwordService.matches(user, oldPassword)){
            return error(Constants.UNVERIFY, "重置密码失败，原密码错误！");
        }
        if (passwordService.matches(user, newPassword)){
            return error(Constants.UNVERIFY, "重置密码失败，新密码与原密码相同！");
        }
        user.setSalt(ShiroUtils.randomSalt());
        //设置新密码
        user.setPassword(passwordService.encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
        if (sysUserService.resetUserPwd(user) > 0) {
            return success("重置密码成功！");
        }
        return error(Constants.UNVERIFY, "服务错误，请稍后重试");
    }

    /**
     * 忘记密码接口
     *
     * @param phoneNumber
     * @param password
     * @param code
     * @return
     */
    @PostMapping("/forgotPassword")
    @ResponseBody
    public Map<String, Object> forgotPassword(String phoneNumber, String password, String code) {
        if (StringUtils.isEmpty(phoneNumber)) {
            return error(Constants.UNVERIFY, "请输入手机号");
        }
        if (StringUtils.isEmpty(code)) {
            return error(Constants.UNVERIFY, "请输入验证码");
        }
        if (StringUtils.isEmpty(password)) {
            return error(Constants.UNVERIFY, "请输入密码");
        }
        //判断手机号
        if (!RegexUtils.isMobile(phoneNumber)) {
            return error(Constants.UNVERIFY, "手机号格式不正确");
        }
        SysUser user = sysUserService.selectUserByPhoneNumber(phoneNumber);
        if (user == null){
            return error(Constants.UNVERIFY,"该手机号未注册,请先注册");
        }
        //校验验证码
        VerificationCode verificationCode = verificationCodeService.selectCodeByNew(phoneNumber);
        String phoneCode = verificationCode.getPhoneCode();
        if (DateUtil.date().getTime() >= verificationCode.getDeadTime().getTime()) {
            return error(Constants.UNVERIFY, "验证码已失效");
        }
        //校验密码长度  都是5-20位
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            return error(Constants.UNVERIFY,"密码格式错误,请输入5到20个字符");
        }
        if (!code.equals(phoneCode)) {
            return error(Constants.UNVERIFY, "验证码错误");
        }
        user.setPassword(passwordService.encryptPassword(user.getLoginName(), password, user.getSalt()));
        if (sysUserService.resetUserPwd(user) > 0) {
            return success("重置密码成功！");
        }else {
            return error(Constants.UNVERIFY,"重置密码失败");
        }
    }

    /**
     * 身份认证接口
     *
     * @return
     */
    @PostMapping("/identityAuthentication")
    @ResponseBody
    public Map<String, Object> identityAuthentication(String token, SysUser user) {
        SysUser sysUser = sysUserService.selectUserById(getUserId(token));
        if (sysUser.getReviewStatus().equals("2")) {
            return error(Constants.UNVERIFY, "认证已审核通过");
        }
        if (sysUser.getReviewStatus().equals("1")) {
            return error(Constants.UNVERIFY, "正在认证审核中");
        }
        if (user.getAttrId() == null) {
            return error(Constants.UNVERIFY, "请选择所属公司");
        }
        LambdaQueryWrapper<CompanyManage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CompanyManage::getCompanyId, user.getAttrId());
        CompanyManage companyManage = companyManageService.getOne(wrapper);
        if (companyManage == null) {
            return error(Constants.UNVERIFY, "该人员不属于公司人员");
        }
        if (StringUtils.isEmpty(user.getUserName())) {
            return error(Constants.UNVERIFY, "请输入姓名");
        }
        sysUser.setAttrId(user.getAttrId());
        sysUser.setSex(user.getSex());
        sysUser.setUserName(user.getUserName());
        sysUser.setReviewStatus("1");
        int row = sysUserService.updateUserInfo(sysUser);
        if (row > 0) {
            return success("提交成功");
        }
        return error(Constants.UNVERIFY, "提交失败");
    }

    /**
     * 通讯录列表接口
     *
     * @return
     */
    @GetMapping("/selectAddressBook")
    @ResponseBody
    public Map<String, Object> selectAddressBook(String token, String userName, Integer pageNum, Integer pageSize) {
        SysUser sysUser = sysUserService.selectUserById(getUserId(token));
        //无归属ID，为平台管理人员,返回空
        if (sysUser == null || StringUtils.isNull(sysUser.getAttrId())) {
            return error(Constants.UNVERIFY, "该用户是平台管理人员");
        }
        SysRole sysRole = sysUserService.checkUserRoleByAttrId(sysUser.getAttrId());
        if (sysRole == null || StringUtils.isEmpty(sysRole.getRoleKey()) || !(sysRole.getRoleKey().equals(BusinessConstants.COMPANY))) {
            return error(Constants.UNVERIFY, "该用户不属于公司人员");
        }

        SysUser user = new SysUser();
        user.setAttrId(sysUser.getAttrId());
        user.setUserName(userName);
        startPage(pageNum, pageSize, "create_time DESC");
        List<SysUser> userList = sysUserService.selectUserList(user);
        for (SysUser sUser : userList) {
            String roles = sysUserService.selectUserRole(sUser.getUserId());

            if(roles.contains(",")){
                String[] roleArray = roles.split(",");

                if(roleArray[0].equals(BusinessConstants.KEEP_MANAGER)){
                    sUser.setRoleName("维保经理");
                }else{
                    sUser.setRoleName("维保工程师");
                }
            }else{
                if(roles.equals(BusinessConstants.KEEP_MANAGER)){
                    sUser.setRoleName("维保经理");
                }else{
                    sUser.setRoleName("维保工程师");
                }
            }
        }

        Map<String, Object> mapReturn = new HashMap<>();
        mapReturn.put("pageNum", pageNum);
        mapReturn.put("list", userList);
        mapReturn.put("total", new PageInfo<>(userList).getTotal());
        return success(mapReturn);
    }


    /**
     * 查看注册协议
     *
     * @return
     */
    @PostMapping("/registerAgreementDetail")
    @ResponseBody
    public Map<String, Object> registerAgreementDetail() {
        RegisterAgreement registerAgreement = registerAgreementService.getById(100L);
        return success(registerAgreement);
    }

}
